/**
 * @description 执行器-控制器
 * @since 2019-11-12
 * @author Rid King
*/

const path = require('path')
const fs = require('fs')
const os = require('os')
const zlib = require('zlib')
const oxjs = require('@daelui/oxjs')
const oxkit = require('@daelui/oxkit')
const Service = require('./service.js')

const nodejs = { path, fs, os, zlib }
const packs = { nodejs, oxjs, oxkit }

class Controller extends oxjs.Controller {
  /**
   * @function 构造方法
  */
  constructor (args) {
    super(args)
    // 服务
    this.$service = new Service(args)
  }

  /**
   * @function 执行
  */
  execute (action, extender) {
    // 解析数据
    return this.solveAction(action, extender).then(async action => {
      return new Promise((resolve, reject) => {
        let params = action.params || {}
        // 包与模块
        let mods = params.mods // 示例：[{ pack: 'oxkit', mod: 'filer' }, { pack: 'nodejs', mod: 'fs' }]
        mods = Array.isArray(mods) ? mods : []
        let args = mods.map(item => {
          let pack = packs[item.pack] || {}
          let mod = pack[item.mod] || {}
          return mod
        })
        args.push((res) => {
          res = res || {}
          res.data = Object.prototype.toString.call(res.data) === '[object Object]' ? res.data : {}
          if (res.status === undefined) {
            res.status = 200
          }
          if (res.success === undefined) {
            res.success = 1
          }
          resolve({
            status: /^\d+$/.test(res.status) ? res.status : undefined,
            success: res.success ? 1 : 0,
            data: res.data,
            msg: typeof res.msg === 'string' ? res.msg : undefined
          })
        })
        // 执行的方法
        let execute = params.execute // 例：function(filer, fs, callback){}
        // 解析
        try {
          execute = new Function('return ' + execute)()
        } catch (e) {
          console.log(e)
          reject({ success: 0, msg: 'execute resolve error' + e.message })
        }
        // 执行
        let isKeepAlive = params.isKeepAlive || false
        let timeout = params.timeout || 30000
        timeout = parseInt(timeout)
        timeout = isNaN(timeout) ? 30000 : timeout
        let isDone = false
        // 非常连接状态下超时处理
        if (!isKeepAlive) {
          setTimeout(function () {
            if (!isDone) {
              reject({ success: 0, msg: 'execute run timeout：' + timeout })
            }
          }, timeout)
        }
        try {
          let result = { success: 1, data: {} }
          let res = execute.apply(this, args) || { success: 1, data: {} }
          if (res instanceof Promise) {
            resolve(res)
          } else if (res.success === 1 || res.success === 0) {
            result = {
              success: res.success,
              data: Object.prototype.toString.call(res.data) === '[object Object]' ? res.data : {},
              msg: typeof res.msg === 'string' ? res.msg : undefined
            }
          }
          isDone = true
          resolve(result)
        } catch (e) {
          reject({ status: e.status, success: e, msg: 'execute run error：' + e.message })
        }
      })
    })
  }
}

module.exports = Controller